package com.mdp.tpa.pay.alipay.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mdp.core.err.BizException;
import com.mdp.tpa.pay.alipay.entity.AlipayNotifyParam;
import com.mdp.tpa.pay.alipay.service.AlipayService;
import com.mdp.tpa.pay.cm.service.OrdersService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@RestController("mall.tpa.AlipayNotifyController")
@RequestMapping(value="/**/pay/alipay")
public class AlipayNotifyController {
	
	private Logger logger= LoggerFactory.getLogger(AlipayNotifyController.class);
	
	ObjectMapper objectMapper=new ObjectMapper();

	@Autowired
	AlipayService alipayService;

	@Autowired
	OrdersService ordersService;

	/*
	 * 支付宝支付成功回调通知
	 */
	@RequestMapping(value="/notify",method=RequestMethod.POST)
	public String zfbNotify(HttpServletRequest request) {
		//将异步通知中收到的待验证所有参数都存放到map中
		final Map<String, String> params = convertRequestParamsToMap(request);
		final String paramsJson = JSON.toJSONString(params);
		logger.debug("支付宝回调：" + paramsJson);
		try {
			// 调用SDK验证签名
			boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayService.pubKey,
					"UTF-8", "RSA2");
			if (signVerified) {
				logger.debug("支付宝回调签名认证成功");
				// 按照支付结果异步通知中的描述，对支付结果中的业务内容进行1\2\3\4二次校验
				// 校验成功后在response中返回success，校验失败返回failure
				this.check(params);
				AlipayNotifyParam param = buildAlipayNotifyParam(params);
				String trade_status = param.getTradeStatus();
				String attachStr=param.getPassbackParams();
				JSONObject attach=JSON.parseObject(attachStr);
				String otype= (String) attach.get("otype");
				String payId= (String) attach.get("payId");
				// 支付成功
				if (trade_status.equals("TRADE_SUCCESS")
						|| trade_status.equals("TRADE_FINISHED")) {
					// 处理支付成功逻辑
					try {
						this.ordersService.payConfirm(otype,param.getOutTradeNo(),payId,param.getTradeNo(),param.getTotalAmount(),"2");
					}catch (BizException e) {
						logger.error("",e);
						return "success";
					} catch (Exception e) {
						logger.error("支付宝回调业务处理报错,params:" + paramsJson);
						logger.error("",e);
						return "failure";
					}
				} else {
					logger.error("没有处理支付宝回调业务，支付宝交易状态：" + trade_status + "params:" + paramsJson);
 				}
				// 如果签名验证正确，立即返回success，后续业务另起线程单独处理
				// 业务处理失败，可查看日志进行补偿，跟支付宝已经没多大关系。
				return "success";
			} else {
				logger.error("支付宝回调签名认证失败，signVerified=false, paramsJson:" + paramsJson);
				return "failure";
			}
		} catch (AlipayApiException e) {
			logger.error("支付宝回调签名认证失败,paramsJson:" + paramsJson + ",errorMsg:" + e.getMessage());
 			return "failure";
		}
	}
	public static BigDecimal ITD100(Integer i){
		if(i==null){
			return BigDecimal.ZERO;
		}else{
			return new BigDecimal(i+"").divide(new BigDecimal("100")); 
		}
	}
	@PostConstruct
	public void initObjectMapper(){
		objectMapper.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.ALWAYS);
		objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		objectMapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); 
		
	}
	/**
	 * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
	 * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
	 * 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
	 * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
	 * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
	 * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
	 *
	 * @param params
	 * @throws AlipayApiException
	 */
	private void check(Map<String, String> params) throws AlipayApiException {
		String outTradeNo = params.get("out_trade_no");

		// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
		if (false) {
			throw new AlipayApiException("out_trade_no错误");
		}

		// 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
		if (false) {
			throw new AlipayApiException("error total_amount");
		}

		// 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
		// 第三步可根据实际情况省略

		// 4、验证app_id是否为该商户本身。
		if (false) {
			throw new AlipayApiException("app_id不一致");
		}
	}
	/**
	 * 把map转为对象
	 *
	 * @param params
	 * @return
	 */
	public AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
		String json = JSON.toJSONString(params);
		return JSON.parseObject(json, AlipayNotifyParam.class);
	}

	/**
	 * 将request中的参数转换成Map
	 *
	 * @param request
	 * @return
	 */
	public static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
		Map<String, String> retMap = new HashMap<String, String>();
		Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
		for (Map.Entry<String, String[]> entry : entrySet) {
			String name = entry.getKey();
			String[] values = entry.getValue();
			int valLen = values.length;
			if (valLen == 1) {
				retMap.put(name, values[0]);
			} else if (valLen > 1) {
				StringBuilder sb = new StringBuilder();
				for (String val : values) {
					sb.append(",").append(val);
				}
				retMap.put(name, sb.toString().substring(1));
			} else {
				retMap.put(name, "");
			}
		}
		return retMap;
	}
	
}
